package drawing 
{
	import app.textures.TextureInfo;
	import app.textures.TextureInfoGroupe;
	import app.textures.TexturePartInfo;
	import core.IDisposable;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import resources.TextureParts;
	import tasks.LoadResource;
	import utils.Logger;
	/**
	 * ...
	 * @author Dmitriy Gaiduk
	 */
	
	  /**
	  * Dispatch when palette prepared
	  */
	[Event(name = "complete", type = "flash.events.Event")]
	public class HybridPalette extends EventDispatcher implements IPalette
	{
		private var _currentType:String;
		
		private var _textureInfo:TextureInfo;
		
		private var _textureProvider:TextureParts = null;
		
		private var _currentPalette: IPaletteDisposable;
		private var _singleTextureLoader:LoadResource;
		
		private var paletteName:String;
		public function HybridPalette(palName:String) 
		{
			paletteName = palName;
		}
		
		
		/**
		 * TextureInfoGroupe textures type
		 * @param	type
		 */
		public function setupTexture(type:String, textureInfo:TextureInfo):void
		{
			if (isProcessRunning())
			{
				throw Error("Cant setup texture. Loading in process not loaded");
			}
			
			switch (type)
			{
				case TextureInfoGroupe.TEXTURE_TYPE_SET_OF_BITMAP:
						if (_currentPalette is BitmapKitPalette)
						{
							if (_textureInfo != null && _textureInfo.sourceURL != textureInfo.sourceURL)
							{
								disposePalette(_currentPalette);
								
								_currentPalette = new BitmapKitPalette(new TextureParts());
							}
						}else
						{
							disposePalette(_currentPalette);
							
							_currentPalette = new BitmapKitPalette(new TextureParts());
						}
					break;
				case TextureInfoGroupe.TEXTURE_TYPE_COLOR:
						if (_currentPalette is ColorPalette)
						{
							(_currentPalette as ColorPalette).color = textureInfo.color;
						}else
						{
							disposePalette(_currentPalette);
							_currentPalette = null;
							_currentPalette = new ColorPalette(textureInfo.color);
						}
					break;
				case TextureInfoGroupe.TEXTURE_TYPE_BITMAP:
						if (_currentPalette is BitmapPalette)
						{
							
							if ((_currentPalette as BitmapPalette).texture != null)
							{
								if (_textureInfo.sourceURL != textureInfo.sourceURL)
								{
									log("dispose bitmap");
									(_currentPalette as BitmapPalette).texture.dispose();
									(_currentPalette as BitmapPalette).texture = null;
								}
							}
							
						}else
						{
							
							disposePalette(_currentPalette);
							_currentPalette = null;
							_currentPalette = new BitmapPalette(null);
						}
					break;
			}
			
			_currentType = type;
			_textureInfo = textureInfo;
			
		}
		
		private function loadSingleTexture():void 
		{
			if (isProcessRunning())
			{
				log("Current process running. Single loader: " + _singleTextureLoader + 
					"; texture parts provider: " + _textureProvider);
					complete();
					return;
			}
			_singleTextureLoader = new LoadResource(_textureInfo.sourceURL, "");
			_singleTextureLoader.run();
			_singleTextureLoader.addEventListener(Event.CHANGE, handleSingleLoaderComplete);
		}
		
		private function handleSingleLoaderComplete(e:Event):void 
		{
			_singleTextureLoader.removeEventListener(Event.CHANGE, handleSingleLoaderComplete);
			if (!_singleTextureLoader.ready)
			{
				log("Single texture loader not complete. file: " + _singleTextureLoader.url);
				_singleTextureLoader = null;
			}
			
			var bitmapPalette:BitmapPalette = _currentPalette as BitmapPalette;
			if (bitmapPalette == null)
			{
				log("Single load complete. Bitmap palette null. current palette: " + _currentPalette);
				return;
			}
			
			var bmData:BitmapData = new BitmapData(_singleTextureLoader.loader.width,
													_singleTextureLoader.loader.height,
													false,
													0xFF0000);
			bmData.draw(_singleTextureLoader.loader);
			bitmapPalette.texture = bmData;
			_singleTextureLoader = null;
			complete();
		}
		
		private function isProcessRunning():Boolean
		{
			return ((_singleTextureLoader != null) || (_textureProvider != null));
		}
		
		public function setupSizes(sizes:Vector.<String>):void
		{
			if (isProcessRunning())
			{
				log("Current process running. Single loader: " + _singleTextureLoader + 
					"; texture parts provider: " + _textureProvider);
			}
			switch (_currentType)
			{
				case TextureInfoGroupe.TEXTURE_TYPE_SET_OF_BITMAP:
						loadTextures(sizes);
					break;
				case TextureInfoGroupe.TEXTURE_TYPE_BITMAP:
						if (_currentPalette is BitmapPalette)
						{
							if ((_currentPalette as BitmapPalette).texture == null)
							{
								loadSingleTexture();
							}else
							{
								complete();
							}
						}else
						{
							log("current palette not bitmapalette: " + _currentPalette);
							complete();
						}
					break;
				case TextureInfoGroupe.TEXTURE_TYPE_COLOR:
						// dispathch complete
						complete();
					break;
			}
			
		}
		
		private function disposePalette(palette:IPaletteDisposable):void
		{
			if (palette == null)
			{
				return;
			}
			if (palette is BitmapKitPalette)
			{
				var bimtapKitPalette:BitmapKitPalette = palette as BitmapKitPalette;
				var partsProvider:TextureParts = bimtapKitPalette.bitmapDataProvider as TextureParts;
				if (partsProvider != null)
				{
					partsProvider.dispose();
				}
			}
			
			palette.dispose();
		}
		
		private function complete():void
		{
			// dispath event
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function loadTextures(sizes:Vector.<String>):void 
		{
			if (_textureProvider != null)
			{
				throw Error("Cant setup size. Current texture not loaded. loadTextures()");
			}
			
			var bitmapKitPalette:BitmapKitPalette = _currentPalette as BitmapKitPalette;
			if (bitmapKitPalette == null)
			{
				log("An error while load textures. current palette not bitmapKitPalette: " + _currentPalette);
				complete();
				return;
			}
			
			var texturesForLoad:Vector.<TexturePartInfo> = new Vector.<TexturePartInfo>();
			
			// get needed textures
			for each (var partInfo:TexturePartInfo in _textureInfo.parts)
			{
				
				if (sizes.indexOf(partInfo.sizeType) > -1)
				{
					texturesForLoad.push(partInfo.clone());
				}
			}
			
			_textureProvider = bitmapKitPalette.bitmapDataProvider as TextureParts;
			if (_textureProvider != null)
			{
				log("Start loading kit textures. total: " + texturesForLoad.length);
				_textureProvider.addEventListener(Event.COMPLETE, handleLoadTexturesComplete);
				_textureProvider.loadTextures(texturesForLoad);
			}else
			{
				log("bitmapKitPalette.bitmapDataProvider is null: " + bitmapKitPalette.bitmapDataProvider);
				complete();
				return;
			}
		}
		
		private function handleLoadTexturesComplete(e:Event):void 
		{
			if (_textureProvider != null)
			{
				_textureProvider.removeEventListener(Event.COMPLETE, handleLoadTexturesComplete);
				_textureProvider = null;
			}else
			{
				log("Somethung wrong on LoadTexturesComplete: textureprovider is null");
			}
			complete();
		}
		
		/* INTERFACE draw.IPalette */
		
		public function beginFill(surface:Graphics, brushType:String, 
									surfaceWidth:Number, surfaceHeight:Number,
									reverseByX:Boolean = false,
									reverseByY:Boolean = false):Boolean 
		{
			if (_currentPalette != null)
			{
				return _currentPalette.beginFill(surface, brushType, 
											surfaceWidth, surfaceHeight,
											reverseByX,
											reverseByY);
			}
			return false;
		}
		
		public function lineStyle(surface:Graphics):Boolean
		{
			if (_currentPalette != null)
			{
				return _currentPalette.lineStyle(surface);
			}
			
			return false;
		}
		
		
		public function endFill(surface:Graphics):void 
		{
			surface.endFill();
		}
		
		private function log(msg:String):void
		{
			Logger.log(this, paletteName + ": " +  msg);
		}
		
		
	}

}